package com.snow.auth.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.snow.auth.controller.SystemUserController;
import com.snow.auth.entity.*;
import com.snow.auth.repository.*;
import com.snow.exception.CommonRuntimeException;
import com.snow.jpa.BaseService;
import com.snow.auth.component.AuthComponent;
import com.snow.starter.SnowAutoConfiguration;
import com.snow.view.IWebResponse;
import com.snow.view.WebResponse;
import lombok.Getter;
import org.springframework.data.domain.Example;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 用户管理
 *
 * @author by 13119
 */
@Getter
@Service
public class SystemUserService extends BaseService<SystemUserRepository, SystemUser, Integer> {
    final SystemUserRoleRepository systemUserRoleRepository;
    final SystemDeptRepository systemDeptRepository;
    private final AuthComponent authComponent;
    private final SnowAutoConfiguration snowAutoConfiguration;
    private final SystemUserPostRepository systemUserPostRepository;
    private final WechatUserRepository wechatUserRepository;

    public SystemUserService(SystemUserRepository repository, SystemUserRoleRepository systemUserRoleRepository, SystemDeptRepository systemDeptRepository, AuthComponent authComponent, SnowAutoConfiguration snowAutoConfiguration, SystemUserPostRepository systemUserPostRepository, WechatUserRepository wechatUserRepository) {
        super(repository);
        this.systemUserRoleRepository = systemUserRoleRepository;
        this.systemDeptRepository = systemDeptRepository;
        this.authComponent = authComponent;
        this.snowAutoConfiguration = snowAutoConfiguration;
        this.systemUserPostRepository = systemUserPostRepository;
        this.wechatUserRepository = wechatUserRepository;
    }

    public IWebResponse create(SystemUserController.CreateParams params) {

        Optional<SystemDept> optionalDept = systemDeptRepository.findById(params.getDeptId());
        if (!optionalDept.isPresent()) {
            return WebResponse.fail("部门信息不存在");
        }
        SystemUser queryParams = new SystemUser();
        queryParams.setAccount(params.getAccount());
        Optional<SystemUser> optionalSystemUser = repository.findOne(Example.of(queryParams));
        if (optionalSystemUser.isPresent()) {
            return WebResponse.fail("账户名已存在，请勿重复创建");
        }
        SystemUser systemUser = BeanUtil.copyProperties(params, SystemUser.class);
        systemUser.setSystemAdmin(false);
        systemUser.setDeptName(optionalDept.get().getDeptName());
        systemUser.setStatus(SystemUser.Status.normal.getValue());
        systemUser.setCreateTime(new Date());
        systemUser.setPassword(DigestUtil.md5Hex(snowAutoConfiguration.getDefaultPwd()).toUpperCase());
        systemUser.setDataScope(params.getDataScope());
        systemUser.setPreviewUser(false);
        systemUser.setTenantId(authComponent.getCurrentUser().getTenantId());
        if (StrUtil.isBlank(systemUser.getAvatar())) {
            systemUser.setAvatar("https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif");
        }
        repository.save(systemUser);
        // 保存用户角色关联关系
        Integer[] roleIds = params.getRoleIds();
        List<SystemUserRole> list = Arrays.stream(roleIds).map(roleId -> new SystemUserRole(systemUser.getId(), roleId, systemUser.getTenantId())).collect(Collectors.toList());
        List<SystemUserPostEntity> postList = Arrays.stream(params.getPostIds()).sequential().map(postId -> new SystemUserPostEntity(systemUser.getId(), postId)).collect(Collectors.toList());
        systemUserRoleRepository.saveAll(list);
        systemUserPostRepository.saveAll(postList);
        return WebResponse.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SystemUser delete(Integer integer) {
        Optional<SystemUser> optionalSystemUser = this.repository.findById(integer);
        if (!optionalSystemUser.isPresent()) {
            throw new CommonRuntimeException("用户信息不存在");
        }
        if (optionalSystemUser.get().getAccount().equals("systemAdmin")) {
            throw new CommonRuntimeException("系统超级管理员禁止删除");
        }
        // 同步删除用户角色关联关系
        systemUserRoleRepository.deleteByUserId(integer);
        // 删除用户
        repository.deleteById(integer);
        return optionalSystemUser.get();
    }

    @Transactional(rollbackFor = Exception.class)
    public void update(SystemUserController.UpdateParams params) {
        SystemUser user = get(params.getId());
        if (user == null) {
            throw new CommonRuntimeException("用户信息不存在，请稍后再试");
        }
        BeanUtil.copyProperties(params, user);
        systemUserRoleRepository.lambdaQuery()
                .equal("userId", user.getId())
                .delete();
        List<SystemUserRole> list = Arrays.stream(params.getRoleIds()).map(userId -> new SystemUserRole(user.getId(), userId, user.getTenantId())).collect(Collectors.toList());
        List<SystemUserPostEntity> postList = Arrays.stream(params.getPostIds()).sequential().map(postId -> new SystemUserPostEntity(user.getId(), postId)).collect(Collectors.toList());
        systemUserRoleRepository.saveAll(list);
        systemUserPostRepository.saveAll(postList);
        save(user);
    }

    @Transactional
    public void bindWeChat(SystemUserController.BindParams params) {
        long count = repository.lambdaQuery().equal("openId", params.getOpenId()).count();
        if (count >= 1) {
            throw new CommonRuntimeException("该微信用户已绑定其他用户");
        }
        SystemUser user = repository.findById(params.getUserId()).orElseThrow(() -> new CommonRuntimeException("用户信息不存在，请稍后再试"));
        if (StrUtil.isNotBlank(user.getOpenId())) {
            throw new CommonRuntimeException("用户已绑定其他微信，请勿重复绑定");
        }
        WechatUserEntity wechatUser = wechatUserRepository.lambdaQuery().findBy("openId", params.getOpenId());
        if (wechatUser == null) {
            throw new CommonRuntimeException("微信用户不存在，请联系管理员");
        }
        user.setOpenId(params.getOpenId());
        repository.save(user);
    }

    @Transactional
    public void unbindWeChat(Integer id) {
        SystemUser user = repository.findById(id).orElseThrow(() -> new CommonRuntimeException("用户信息不存在，请稍后再试"));
        if (StrUtil.isBlank(user.getOpenId())) {
            throw new CommonRuntimeException("用户尚未绑定微信，无法解绑");
        }
        user.setOpenId(null);
        repository.save(user);
    }

    @Transactional(rollbackFor = Exception.class)
    public void linkWechat(SystemUserController.LinkWechatParams params) {
        WechatUserEntity wechatUser = wechatUserRepository.findBy("phone", params.getPhone());
        if (wechatUser == null) {
            throw new CommonRuntimeException("微信用户不存在");
        }
        SystemUser systemUser = get(params.getUserId());
        if (systemUser == null) {
            throw new CommonRuntimeException("用户信息不存在");
        }
        wechatUser.setUserId(systemUser.getId());
        wechatUserRepository.save(wechatUser);
        systemUser.setOpenId(wechatUser.getOpenId());
        save(systemUser);
    }
}
